In this article, we make an Arduino Countdown Timer using P10 Display. The counting is done by Arduino and then displayed in the P10 LED module. This project might come in handy for time-keeping purposes during physical games. The details about pin configuration, display specifications, and hardware interfacing between Arduino Nano and P10 are referenced from the “Interfacing P10 single color LED Display with Arduino Nano” article. In this article you will learn two things:
- How to display a countdown of 3 minutes in P10.
- How to include a Reset feature in the countdown if necessary.
Components Required:
- Arduino Nano x1
- P10 display module x1
- Jumper wires(M to F) x15
- Bread Board x1
- 10kΩ resistors x2
- push buttons(start & Pause) x2
- 5V power supply (2Amps) x1
Circuit Description of Arduino Countdown Timer using P10 Display
The connection of the Arduino Countdown Timer using the P10 Display is the same as shown in the previous post “Interfacing P10 single color LED Display with Arduino Nano” with two extra push switches and corresponding pull-down resistors. Switch SW1 is used to start the timer whereas switch SW2 is used to reset the timer.
Displaying a Countdown Timer of 3 Minutes:
We are aiming to display a message “PRESS START” to initiate a countdown. Then after the button is pressed the countdown is shown on the P10 display. Let’s fix the timer to 3 minutes. Lastly, after the counter reaches 0 seconds, it displays Time UP. The code for this program is broken down and explained below.
- Include necessary libraries and define some variables.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <SPI.h> #include <DMD.h> #include <TimerOne.h> #include "SystemFont5x7.h" #include "Arial_black_16.h" #define DISPLAYS_ACROSS 1 #define DISPLAYS_DOWN 1 String str; char b[8]; int menit,detik,x; const int StartButton = A0; int StartButtonPress = 0; int StartButtonState = 0; DMD dmd(DISPLAYS_ACROSS, DISPLAYS_DOWN); |
Some important libraries such as <SPI.h> for Serial communication, <DMD.h> for P10 display operations and <TimerOne.h> for interrupt tasks, need to be included in the program. Include the display font library <Arial_black_16.h> and <SystemFont5x7.h> for large and small sized text displays. Also, initialize StartButton as A0, char type array “b[]” and string variable “str” as shown in code. The “StartButtonPress, StartButtonState, and StartButton” variables are used for Starting the countdown action of the timer.
- Define Scan_module() function:
1 2 |
void ScanDMD() {dmd.scanDisplayBySPI();} |
scan_module() function will check for any incoming data from the Arduino side through the SPI Terminals. If yes, then it will trigger an interrupt pin for certain events.
- Initialize the Setup function:
1 2 3 4 5 6 7 8 9 |
void setup() { Serial.begin(9600); pinMode(StartButton, INPUT); Timer1.initialize(5000); Timer1.attachInterrupt(ScanDMD); dmd.clearScreen(true); Serial.println("Press Start Button"); } |
Inside setup() set the StartButton in INPUT mode, then initialize the timer and attach the interrupt to the function scan_module() with 5000-microsecond intervals. Here dmd.clearScreen(true) is used to set all pixels LEDs in off state and clear the display board.
- Define a CheckStartButton() function:
The CheckStartButton() function waits and checks if the start button is pressed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
void CheckStartButton() { int slen = 0; // length of string detik = 0; // clearing the seconds to start fresh dmd.clearScreen( true ); dmd.selectFont(SystemFont5x7); str="Press"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 0, 0, b, slen, GRAPHICS_NORMAL ); str="Start"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 0, 8, b, slen, GRAPHICS_NORMAL ); while(1) { StartButtonPress = digitalRead(StartButton); delay(5); if(StartButtonPress == HIGH) { dmd.clearScreen( true ); Serial.println("Start Button Pressed"); StartButtonState = 1; dmd.selectFont(SystemFont5x7); str="Start"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 0, 0, b, slen, GRAPHICS_NORMAL ); str="in:"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 0, 8, b, slen, GRAPHICS_NORMAL ); int i = 0; Serial.println("Starts in: "); for( i=3; i>0; i--) { str=String(i); str.toCharArray(b,2); dmd.selectFont(SystemFont5x7); dmd.drawString( 15,8, b,2, GRAPHICS_NORMAL ); Serial.println(i); delay(1000); } Serial.println("-------"); str = "3:00"; Serial.println(str); slen = str.length()+1; dmd.selectFont(Arial_Black_16); dmd.drawString( 0, 0, "3:00", slen, GRAPHICS_NORMAL ); delay(1000); return; } } } |
- Programming the Void loop() function:
Here the program begins by waiting for the start button to be pressed with the help of the CheckStartButton() function. Then, after the start button is pressed it provides an interactive countdown of 3 minutes. The countdown is displayed at the P10 module as well as in the serial monitor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
void loop() { CheckStartButton(); //waiting for start button to be pressed x=1; str=""; menit=3; // set minutes to 3 min while(x) { int slen = 0; // variable to store string length //min and sec reduction process if(detik>0) {detik--;} else if(detik==0) { detik=59; if(menit>0) {menit--;} else if(menit==0) { detik=0;//seconds x=0; } } //display countdown dmd.clearScreen( true ); if(detik<10){str=String(menit)+":0"+String(detik);} else{str=String(menit)+":"+String(detik);} slen = str.length()+1; str.toCharArray(b,slen); dmd.selectFont(Arial_Black_16); dmd.drawString( 0, 0, b, slen, GRAPHICS_NORMAL ); Serial.println(str); //Time up case if(menit == 0 && detik == 0) { Serial.print("Normal Time End"); Serial.println("Time Up"); Serial.println("Press Start button to Start Again"); dmd.clearScreen( true ); dmd.selectFont(SystemFont5x7); str="Time"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 4, 0, b, slen, GRAPHICS_NORMAL ); str="Up"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 8, 8, b, slen, GRAPHICS_NORMAL ); delay(2000); x=0; // if TimeUp get out of while(x) loop } //one second delay for Countdown delay(1000); } } |
- Code for Display countdown with Reset feature:
During the counting process, if a Reset button is pressed, the countdown resets the Countdown process. After resetting the program starts with a “PRESS START” message indicating the completion of the reset process.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
#include <SPI.h> #include <DMD.h> #include <TimerOne.h> #include "SystemFont5x7.h" #include "Arial_black_16.h" #define DISPLAYS_ACROSS 1 #define DISPLAYS_DOWN 1 int menit,detik,i; const int StartButton = A0; const int ResetButton = A1; //Here, another button A1 [Reset] is introduced. char b[8]; String str; DMD dmd(DISPLAYS_ACROSS, DISPLAYS_DOWN);] void ScanDMD(){ dmd.scanDisplayBySPI(); } void CheckStartButton() { int slen = 0;// length of string detik = 0;// clearing the seconds to start fresh dmd.clearScreen( true ); dmd.selectFont(SystemFont5x7); str="Press"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 0, 0, b, slen, GRAPHICS_NORMAL ); str="Start"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 0, 8, b, slen, GRAPHICS_NORMAL ); while(1) { StartButtonPress = digitalRead(StartButton); delay(5); if(StartButtonPress == HIGH) { dmd.clearScreen( true ); Serial.println("Start Button Pressed"); StartButtonState = 1; dmd.selectFont(SystemFont5x7); str="Start"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 0, 0, b, slen, GRAPHICS_NORMAL ); str="in:"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 0, 8, b, slen, GRAPHICS_NORMAL ); int i = 0; Serial.println("Starts in: "); for( i=3; i>0; i--) { str=String(i); str.toCharArray(b,2); dmd.selectFont(SystemFont5x7); dmd.drawString( 15,8, b,2, GRAPHICS_NORMAL ); Serial.println(i); delay(1000); } Serial.println("-------"); str = "3:00"; Serial.println(str); slen = str.length()+1; dmd.selectFont(Arial_Black_16); dmd.drawString( 0, 0, "3:00", slen, GRAPHICS_NORMAL ); delay(1000); return; } } } void setup() { Serial.begin(9600); pinMode(StartButton, INPUT); pinMode(ResetButton, INPUT); Timer1.initialize(5000); Timer1.attachInterrupt(ScanDMD); dmd.clearScreen(true); Serial.println("Press Start Button"); } void loop() { CheckStartButton();//does not move forward untill Start button is pressed int ResetButtonPress = 0; //for reading value from StartButton int ResetButtonState = 0; //initializing the button state x=1; str=""; menit=3;//minutes while(x) { int slen = 0; ResetButtonPress = digitalRead(ResetButton); //read the button value to Stop //min and sec reduction process if(detik>0) {detik--;} else if(detik==0) { detik=59; if(menit>0) {menit--;} else if(menit==0) { detik=0;//seconds x=0; } } // For stoping action if(ResetButtonState == 1) { Serial.println("Stopped Timer"); Serial.println("Press Start button to Start Again"); dmd.clearScreen( true ); dmd.selectFont(SystemFont5x7); str="Reset"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 0, 0, b, slen, GRAPHICS_NORMAL ); str="Time"; str.toCharArray(b,6); slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 0, 8, b, slen, GRAPHICS_NORMAL ); delay(2000); x=0; ResetButtonState = 0; break;// get out of while loop } //display countdown dmd.clearScreen( true ); if(detik<10){str=String(menit)+":0"+String(detik);} else{str=String(menit)+":"+String(detik);} slen = str.length()+1; str.toCharArray(b,slen); dmd.selectFont(Arial_Black_16); dmd.drawString( 0, 0, b, slen, GRAPHICS_NORMAL ); Serial.println(str); //Time up case if(menit == 0 && detik == 0) { Serial.print("Normal Time End"); Serial.println("Time Up"); dmd.clearScreen( true ); dmd.selectFont(SystemFont5x7); str="Time"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 4, 0, b, slen, GRAPHICS_NORMAL ); str="Up"; slen = str.length()+1; str.toCharArray(b,slen); dmd.drawString( 8, 8, b, slen, GRAPHICS_NORMAL ); delay(2000); x=0; //TimeUp get out of while } if(ResetButtonPress == 1) { Serial.println("Reset Button Pressed"); ResetButtonState = 1; } //one second delay delay(1000); } } |